from __future__ import with_statement

import urllib
import json
import logging
import httplib2
import uuid
import urllib2
from poster.encode import multipart_encode, MultipartParam
from poster.streaminghttp import register_openers
import cStringIO
from StringIO import StringIO
from time import time
import binascii

import webapp2
from webapp2_extras import sessions
from webapp2_extras import jinja2

from google.appengine.api import urlfetch
from google.appengine.ext import db
from google.appengine.api import images
from google.appengine.api import files

from models import User
import config
from utils import build_url, serialize, generate_hash

logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s %(message)s',
        datefmt='[%Y-%m-%d %H:%M:%S %z]',
    )

class BaseHandler(webapp2.RequestHandler):
    def dispatch(self):
        # Get a session store for this request.
        self.session_store = sessions.get_store(request=self.request)
        try:
            # Dispatch the request.
            webapp2.RequestHandler.dispatch(self)
        finally:
            # Save all sessions.
            self.session_store.save_sessions(self.response)

    @webapp2.cached_property
    def session(self):
        # Returns a session using the default cookie key.
        return self.session_store.get_session()
    
    @webapp2.cached_property
    def jinja2(self):
        # Returns a Jinja2 renderer cached in the app registry.
        return jinja2.get_jinja2(app=self.app)

    def render_response(self, _template, **context):
        # Renders a template and writes the result to the response.
        rv = self.jinja2.render_template(_template, **context)
        self.response.write(rv)
        
class Index(BaseHandler):
    
    def get(self):
        
        ig_user_id = self.session.get('ig_user_id')
        sc_user_id = self.session.get('sc_user_id')
        
        user = User.all().filter('ig_user_id =', ig_user_id).get() or User.all().filter('sc_user_id =', sc_user_id).get()
            
        ig_params = {
            'client_id': config.IG_CLIENT_ID,
            'redirect_uri': config.IG_REDIRECT_URI,
            'response_type': 'code'
        }
        ig_auth_url = build_url(config.IG_AUTH_URL, ig_params)
        
        sc_params = {
            'client_id': config.SC_CLIENT_ID,
            'redirect_uri': config.SC_REDIRECT_URI,
            'response_type': 'code'
        }
        sc_auth_url = build_url(config.SC_AUTH_URL, sc_params)
        
        context = {
           'user': user,
           'ig_auth_url': ig_auth_url,
           'sc_auth_url': sc_auth_url,
        }
        
        self.render_response('index.html', **context)
            
class InstagramCallback(BaseHandler):
    
    def get(self):
        
        code = self.request.get('code')
        
        params = {
            'client_id': config.IG_CLIENT_ID,
            'client_secret': config.IG_CLIENT_SECRET,
            'redirect_uri': config.IG_REDIRECT_URI,
            'grant_type': 'authorization_code',
            'code': code
        }
                
        data = urllib.urlencode(params)
        h = httplib2.Http()
        response, content = h.request(config.IG_TOKEN_URL, method='POST', body=data)
        ig_access_token = json.loads(content)['access_token']
        
        ig_params = { 'access_token': ig_access_token }

        response, content = h.request(build_url('https://api.instagram.com/v1/users/self', ig_params))
        ig_me = json.loads(content)
        
        ig_user_id = ig_me['data']['id']
        ig_username = ig_me['data']['username']
        ig_full_name = ig_me['data']['full_name']
        
        user = User.all().filter('sc_user_id = ', self.session.get('sc_user_id')).get() or User()
            
        user.ig_access_token = ig_access_token
        user.ig_user_id = ig_user_id
        user.ig_username = ig_username
        user.ig_full_name = ig_full_name
    
        user.put()
        
        self.session['ig_user_id'] = ig_user_id
        
        self.redirect('/')
    
class InstagramDisconnect(BaseHandler):
    
    def get(self):
        
        user = User.all().filter('ig_user_id = ', self.session.get('ig_user_id')).get()
        
        if user.sc_user_id:
            
            user.ig_access_token = None
            user.ig_user_id = None
            user.ig_username = None
            user.ig_full_name = None
            
            user.put()
        
        else:
            
            user.delete()
        
        del self.session['ig_user_id']
        
        self.redirect('/')
    
class SoundCloudCallback(BaseHandler):
    
    def get(self):
        
        code = self.request.get('code')
        
        params = {
            'client_id': config.SC_CLIENT_ID,
            'client_secret': config.SC_CLIENT_SECRET,
            'redirect_uri': config.SC_REDIRECT_URI,
            'grant_type': 'authorization_code',
            'code': code
        }
                
        data = urllib.urlencode(params)
        h = httplib2.Http()
        response, content = h.request(config.SC_TOKEN_URL, method='POST', body=data)
        sc_access_token = json.loads(content)['access_token']
        
        sc_params = { 'oauth_token': sc_access_token }

        response, content = h.request(build_url('https://api.soundcloud.com/me.json', sc_params))
        sc_me = json.loads(content)
        
        sc_user_id = str(sc_me['id'])
        sc_username = sc_me['username']
        sc_full_name = sc_me['full_name']
                
        user = User.all().filter('ig_user_id = ', self.session.get('ig_user_id')).get() or User()
            
        user.sc_access_token = sc_access_token
        user.sc_user_id = sc_user_id
        user.sc_username = sc_username
        user.sc_full_name = sc_full_name
    
        user.put()
        
        self.session['sc_user_id'] = sc_user_id
        
        self.redirect('/')
        
    
class SoundCloudDisconnect(BaseHandler):
    
    def get(self):
        
        user = User.all().filter('sc_user_id = ', self.session.get('sc_user_id')).get()
            
        if user.ig_user_id:
            
            user.sc_access_token = None
            user.sc_user_id = None
            user.sc_username = None
            user.sc_full_name = None
            
            user.put()
        
        else:
            
            user.delete()
        
        del self.session['sc_user_id']
        
        self.redirect('/')
        
class Images(BaseHandler):
    
    def get(self):
        
        if self.session.get('ig_user_id') and self.session.get('sc_user_id'):
            
            ig_user_id = self.session.get('ig_user_id')
            sc_user_id = self.session.get('sc_user_id')
        
            user = User.all().filter('ig_user_id =', ig_user_id).get() or User.all().filter('sc_user_id =', sc_user_id).get()
        
            h = httplib2.Http()
            
            ig_params = { 'access_token': user.ig_access_token }
    
            response, content = h.request(build_url('https://api.instagram.com/v1/users/self/media/recent', ig_params))
            ig_media = json.loads(content)
    
            ig_media_list = [ image['images'] for image in ig_media['data'] ]
            
            context = {
               'user': user,
               'images': ig_media_list,
            }
            
            self.render_response('images.html', **context)
            
        else:
            
            self.redirect('/')
            
    def post(self):
        
        self.session['image_url'] = self.request.get('image_url')
        
        self.redirect('/sets')
        
            
class Sets(BaseHandler):
    
    def get(self):
        
        if self.session.get('ig_user_id') and self.session.get('sc_user_id'):
            
            ig_user_id = self.session.get('ig_user_id')
            sc_user_id = self.session.get('sc_user_id')
        
            user = User.all().filter('ig_user_id =', ig_user_id).get() or User.all().filter('sc_user_id =', sc_user_id).get()
        
            h = httplib2.Http()
            
            sc_params = { 'oauth_token': user.sc_access_token }
    
            # response, content = h.request(build_url('https://api.soundcloud.com/me/tracks.json', sc_params))
            # sc_tracks = json.loads(content)
            
            # track_uri_list = [ track['uri'] for track in sc_tracks ]
    
            response, content = h.request(build_url('https://api.soundcloud.com/me/playlists.json', sc_params))
            sc_sets = json.loads(content)
            
            # set_uri_list = [ set['uri'] for set in sc_sets ]
            
            context = {
               'user': user,
               'image_url': self.session.get('image_url'),
               # 'tracks': sc_tracks,
               'sets': sc_sets,
            }
            
            self.render_response('sets.html', **context)
            
        else:
            
            self.redirect('/')
            
            
    def post(self):
        
        self.session['set_uri'] = self.request.get('set_uri')
        
        self.redirect('/bind')
        
        
class Bind(BaseHandler):
    
    def get(self):
        
        if self.session.get('ig_user_id') and self.session.get('sc_user_id'):
            
            ig_user_id = self.session.get('ig_user_id')
            sc_user_id = self.session.get('sc_user_id')
        
            user = User.all().filter('ig_user_id =', ig_user_id).get() or User.all().filter('sc_user_id =', sc_user_id).get()
            
            context = {
               'user': user,
               'image_url': self.session.get('image_url'),
               'set_uri': self.session.get('set_uri'),
            }
            
            self.render_response('bind.html', **context)
            
        else:
            
            self.redirect('/')
            
            
    def post(self):
        
        if self.session.get('ig_user_id') and self.session.get('sc_user_id'):
            
            ig_user_id = self.session.get('ig_user_id')
            sc_user_id = self.session.get('sc_user_id')
        
            user = User.all().filter('ig_user_id =', ig_user_id).get() or User.all().filter('sc_user_id =', sc_user_id).get()
            
            response = urllib2.urlopen(self.session.get('image_url'))
            content = response.read()
            
            params = []
            params.append(MultipartParam('playlist[artwork_data]', filename=("%s.jpg" % int(time())), filetype='application/octet-stream', value=content))
            params.append(MultipartParam('oauth_token', user.sc_access_token))
            
            datagen, headers = multipart_encode(params)
            data = str().join(datagen)
            result = urlfetch.fetch(url=self.session.get('set_uri'), payload=data, method=urlfetch.PUT, headers=headers, deadline=10)
        
            self.redirect('/')